热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

枢轴|所指_王道数据结构8(排序)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了王道数据结构8(排序)相关的知识,希望对你有一定的参考价值。排序排序

篇首语:本文由编程笔记#小编为大家整理,主要介绍了王道数据结构8(排序)相关的知识,希望对你有一定的参考价值。



排序


  • 排序
    • 一.概念
      • 【1】稳定排序和不稳定排序
      • 【2】排序分类


  • 二. 插入排序
    • 【1】直接插入排序
      • 1. 算法
      • 2.算法实例
      • 3. 算法评价

    • 【2】二叉法插入
      • 1.算法
      • 2. 算法评价

    • 【3】希尔排序(缩小增量法)
      • 1.算法过程
      • 2. 例子
      • 3.算法
      • 4.希尔排序特点


  • 三.交换排列
    • 【1】起泡排序
      • 1.排序过程
      • 2. 算法
      • 3.算法评价

    • 【2】快速排序
      • 1. 基本思想
      • 2.一个例子
      • 3. 算法
      • 4.算法评价


  • 四. 选择排序
    • 【1】简单选择排序
      • 1. 排序过程
      • 2.一个例子
      • 3. 算法
      • 4. 算法评价

    • 【2】堆排序
      • 1.建立堆
      • 2.排序法
      • 3.算法
      • 4.算法评价


  • 五.分配排序
    • 【1】分配排序的思想
    • 【2】一个例子
    • 【3】算法评价

  • 六.归并排序
    • 【1】排序过程
    • 【2】算法评价

  • 七.总结


排序

一.概念


【1】稳定排序和不稳定排序

假设Ki&#61;Kj(0<&#61;i,j<&#61;n-1,i不等于j)&#xff0c;且在排序前的序列中Ri领先于Rj(即i

【2】排序分类


  1. 按待排序记录所在位置

  • 内部排序&#xff1a;待排序记录存放在内存
  • 外部排序&#xff1a;排序过程中需对外存进行访问的排序

  1. 按排序依据原则

  • 插入排序&#xff1a;直接插入排序、折半插入排序、希尔排序、表插入排序*
  • 交换排序&#xff1a;起泡排序、快速排序
  • 选择排序&#xff1a;简单选择排序、堆排序
  • 归并排序&#xff1a;2-路归并排序
  • 分配排序

  1. 按排序所需工作量

  • 简单的排序方法&#xff1a;T(n)&#61;O(n²)
  • 先进的排序方法&#xff1a;T(n)&#61;O(logn)

  1. 排序算法的衡量标准&#xff1a;

  • 空间开销&#xff1a;执行算法所需的附加空间
  • 时间开销&#xff1a;执行算法所需的时间。通常用算法执行中的比较和移动次数来衡量。考虑最坏和平均情况。

二. 插入排序

【1】直接插入排序


1. 算法

整个排序过程为n-1趟插入&#xff0c;即先将序列中第1个记录看成是一个有序子序列&#xff0c;然后从第2个记录开始&#xff0c;逐个进行插入&#xff0c;直至整个序列有序

typedef struct
int key;
float info;
JD;
void straisort(JD r[],int n)
int i,j;
for(i&#61;2;i<&#61;n;i&#43;&#43;)
r[0]&#61;r[i];
j&#61;i-1;
while(r[0].key<r[j].key)
r[j&#43;1]&#61;r[j];
j--;
r[j&#43;1]&#61;r[0];


2.算法实例


3. 算法评价


  1. 时间复杂度
    T(n)&#61;O(n2)
  2. 空间复杂度
    S(n)&#61;O(1)

【2】二叉法插入


1.算法

void binsort(JD r[],int n)
int i,j,x,s,m,k;
for(i&#61;2;i<&#61;n;i&#43;&#43;)
r[0]&#61;r[i];
x&#61;r[i].key;
s&#61;1; j&#61;i-1;
while(s<&#61;j)
m&#61;(s&#43;j)/2;
if(x<r[m].key) j&#61;m-1;
else s&#61;m&#43;1;

for(k&#61;i-1;k>&#61;s;k--)
r[k&#43;1]&#61;r[k];
r[s]&#61;r[0];



2. 算法评价


  • 时间复杂度&#xff1a;T(n)&#61;O(n²)
  • 空间复杂度&#xff1a;S(n)&#61;O(1)

【3】希尔排序(缩小增量法)


1.算法过程

排序过程&#xff1a;先取一个正整数d1

2. 例子


3.算法

void shellsort(JD r[],int n,int d[T])
int i,j,k;
JD x;
k&#61;0;
while(k<T)
for(i&#61;d[k]&#43;1;i<&#61;n;i&#43;&#43;)
x&#61;r[i];
j&#61;i-d[k];
while((j>0)&&(x.key<r[j].key))
r[j&#43;d[k]]&#61;r[j];
j&#61;j-d[k];

r[j&#43;d[k]]&#61;x;

k&#43;&#43;;




4.希尔排序特点


  • 子序列的构成不是简单的“逐段分割”&#xff0c;而是将相隔某个增量的记录组成一个子序列
  • 希尔排序可提高排序速度&#xff0c;因为 &#xff1a;
  • 分组后n值减小&#xff0c;n²更小&#xff0c;而T(n)&#61;O(n²),所以T(n)从总体上看是减小了
  • 关键字较小的记录跳跃式前移&#xff0c;在进行最后一趟增量为1的插入排序时&#xff0c;序列已基本有序
  • 增量序列取法
  • 无除1以外的公因子(或者di&#43;1&#61;|_ di/2 _|)
  • 最后一个增量值必须为1

三.交换排列

【1】起泡排序


1.排序过程


  • 将第一个记录的关键字与第二个记录的关键字进行比较&#xff0c;若为逆序r[1].key>r[2].key&#xff0c;则交换&#xff1b;然后比较第二个记录与第三个记录&#xff1b;依次类推&#xff0c;直至第n-1个记录和第n个记录比较为止——第一趟冒泡排序&#xff0c;结果关键字最大的记录被安置在最后一个记录上
  • 对前n-1个记录进行第二趟冒泡排序&#xff0c;结果使关键字次大的记录被安置在第n-1个记录位置
  • 重复上述过程&#xff0c;直到“在一趟排序过程中没有进行过交换记录的操作”为止

2. 算法

void bubble_sort(JD r[],int n)
int m,i,j,flag&#61;1;
JD x;
m&#61;n-1;
while((m>0)&&(flag&#61;&#61;1))
flag&#61;0;
for(j&#61;1;j<&#61;m;j&#43;&#43;)
if(r[j].key>r[j&#43;1].key)
flag&#61;1;
x&#61;r[j];
r[j]&#61;r[j&#43;1];
r[j&#43;1]&#61;x;
m--;

3.算法评价


  1. 时间复杂度&#xff1a;T(n)&#61;O(n²)

  • 最好情况&#xff08;正序&#xff09;
  • 比较次数&#xff1a;n-1 移动次数&#xff1a;0
  • 最坏情况&#xff08;逆序&#xff09; 比较次数&#xff1a;

移动次数&#xff1a;


  • 空间复杂度&#xff1a;S(n)&#61;O(1)

【2】快速排序


1. 基本思想

通过一趟排序&#xff0c;将待排序记录分割成独立的两部分&#xff0c;其中一部分记录的关键字均比另一部分记录的关键字小&#xff0c;则可分别对这两部分记录进行排序&#xff0c;以达到整个序列有序
排序过程&#xff1a;对r[s……t]中记录进行一趟快速排序&#xff0c;附设两个指针i和j&#xff0c;设枢轴记录rp&#61;r[s]&#xff0c;x&#61;rp.key


  • 初始时令i&#61;s,j&#61;t
  • 首先从j所指位置向前搜索第一个关键字小于x的记录&#xff0c;并和rp交换
  • 再从i所指位置起向后搜索&#xff0c;找到第一个关键字大于x的记录&#xff0c;和rp交换
  • 重复上述两步&#xff0c;直至i&#61;&#61;j为止
  • 再分别对两个子序列进行快速排序&#xff0c;直到每个子序列只含有一个记录为止

2.一个例子


3. 算法

void qksort(JD r[],int t,int w)
int i,j,k;
JD x;
if(t>&#61;w) return;
i&#61;t; j&#61;w; x&#61;r[i];
while(i<j)
while((i<j)&&(r[j].key>&#61;x.key)) j--;
if(i<j) r[i]&#61;r[j]; i&#43;&#43;;
while((i<j)&&(r[i].key<&#61;x.key)) i&#43;&#43;;
if(i<j) r[j]&#61;r[i]; j--;
r[i]&#61;x; qksort(r,t,j-1);
qksort(r,j&#43;1,w);

4.算法评价


  • 时间复杂度 T(n)&#61;O(n²)
  • 最好情况&#xff08;每次总是选到中间值作枢轴&#xff09;T(n)&#61;O(nlog2n)
  • 最坏情况&#xff08;每次总是选到最小或最大元素作枢轴&#xff09;T(n)&#61;O(n²)
  • 空间复杂度&#xff1a;需栈空间以实现递归
  • 最坏情况&#xff1a;S(n)&#61;O(n)
  • 一般情况&#xff1a;S(n)&#61;O(log2n)

四. 选择排序

【1】简单选择排序


1. 排序过程


  • .首先通过n-1次关键字比较&#xff0c;从n个记录中找出关键字最小的记录&#xff0c;将它与第一个记录交换
  • 再通过n-2次比较&#xff0c;从剩余的n-1个记录中找出关键字次小的记录&#xff0c;将它与第二个记录交换
  • 重复上述操作&#xff0c;共进行n-1趟排序后&#xff0c;排序结束

2.一个例子


3. 算法

void smp_selesort(JD r[],int n)
int i,j,k;
JD x;
for(i&#61;1;i<n;i&#43;&#43;)
k&#61;i;
for(j&#61;i&#43;1;j<&#61;n;j&#43;&#43;)
if(r[j].key<r[k].key) k&#61;j;
if(i!&#61;k)
x&#61;r[i];
r[i]&#61;r[k];
r[k]&#61;x;


4. 算法评价


  • 时间复杂度
    -最好情况&#xff1a;0
    最坏情况&#xff1a;3&#xff08;n-1&#xff09;
    T(n)&#61;O(n2)

  • 空间复杂度

  • S&#xff08;n&#xff09;&#61;O(1)


【2】堆排序


1.建立堆


2.排序法


3.算法

void heapsort(JD r[],int n)
int i;
JD x;
for(i&#61;n/2;i>&#61;1;i--)
sift(r,i,n);
for(i&#61;n;i>&#61;2;i--)
x&#61;r[1];
r[1]&#61;r[i];
r[i]&#61;x;
sift(r,1,i-1);

int sift(JD r[],int k,int m)
int i,j;
JD x;
i&#61;k; x&#61;r[i]; j&#61;2*i;
while(j<&#61;m)
if((j<m)&&r[j].key>r[j&#43;1].key))
j&#43;&#43;;
if(x.key>r[j].key)
r[i]&#61;r[j];
i&#61;j; j&#61;j*2;
else j&#61;m&#43;1;

r[i]&#61;x;

4.算法评价


  • 时间复杂度
  • 最坏情况下T(n)&#61;O(nlogn)
  • 空间复杂度&#xff1a;
  • S(n)&#61;O(1)

五.分配排序

【1】分配排序的思想

把排序码分解成若干部分&#xff0c;然后通过对各个部分排序码的分别排序&#xff0c;最终达到整个排序码的排序


【2】一个例子




【3】算法评价


  • 时间复杂度&#xff1a; T(n)&#61;O(d*(r&#43;n))。

基数排序算法中&#xff0c;时间耗费主要在修改指针上。一趟排序的时间为O(r&#43;n)。总共要进行d趟排序&#xff1b;
当n较大、d较小&#xff0c;特别是记录的信息量较大时&#xff0c;基数排序非常有效。


  • 空间复杂度&#xff1a; S(n)&#61;O(n&#43;r)。

基数排序中&#xff0c;每个记录中增加了一个next字段&#xff0c;还增加了一个queue数组。


  • 基数排序是稳定的。

六.归并排序

【1】排序过程


  • 设初始序列含有n个记录&#xff0c;则可看成n个有序的子序列&#xff0c;每个子序列长度为1
  • 两两合并&#xff0c;得到n/2个长度为2或1的有序子序列
  • 再两两合并&#xff0c;……如此重复&#xff0c;直至得到一个长度为n的有序序列为止

【2】算法评价

时间复杂度&#xff1a;T(n)&#61;O(nlog2n)
空间复杂度&#xff1a;S(n)&#61;O(n)


七.总结


&#xff08;1&#xff09;平均时间性能&#xff1a;以快速排序法最佳&#xff0c;但最坏情况下不如堆排序和归并排序&#xff1b;在n较大时&#xff0c;归并排序比堆排序快&#xff0c;但所需辅助空间最多。
&#xff08;2&#xff09;简单排序以直接插入排序最简单&#xff0c;当下列中记录“基本有序“或n值较小时&#xff0c;是最佳的排序方法。因此常和其他排序方法结合使用。
&#xff08;3&#xff09;基数排序最适用于n值很大而关键字较小的序列。若关键字也很大&#xff0c;而序列中大多数记录的”最高位关键字”均不同&#xff0c;则也可以先按“最高位关键字”不同将序列分成若干个子序列&#xff0c;而后用直接插入排序。
&#xff08;4&#xff09;从稳定性来看&#xff0c;基数排序是稳定的排序方法&#xff0c;大部分时间复杂度为O(n2)的简单排序法都是稳定的。然而&#xff0c;快速排序、堆排序和希尔排序等时间性能较好的排序都是不稳定的。一般来说&#xff0c;排序过程中的比较是在相邻的两个记录关键字之间进行的排序方法是稳定的。大多数情况下排序是按记录的主关键字进行的&#xff0c;则所有的排序方法是否稳定无关紧要。当排序是按记录的次关键字进行时&#xff0c;则应根据问题所需慎重选择。


推荐阅读
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 设计模式——模板方法模式的应用和优缺点
    本文介绍了设计模式中的模板方法模式,包括其定义、应用、优点、缺点和使用场景。模板方法模式是一种基于继承的代码复用技术,通过将复杂流程的实现步骤封装在基本方法中,并在抽象父类中定义模板方法的执行次序,子类可以覆盖某些步骤,实现相同的算法框架的不同功能。该模式在软件开发中具有广泛的应用价值。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文介绍了一种图的存储和遍历方法——链式前向星法,该方法在存储带边权的图时时间效率比vector略高且节省空间。然而,链式前向星法存图的最大问题是对一个点的出边进行排序去重不容易,但在平行边无所谓的情况下选择这个方法是非常明智的。文章还提及了图中搜索树的父子关系一般不是很重要,同时给出了相应的代码示例。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
author-avatar
werwd2_736
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有